package org.x.note.string;

import java.util.Date;

public class MoneyUtil {

	/**
	 * 繁体数字
	 */
	public static String[] DIGITS_CN = new String[] { "零", "壹", "贰", "叁", "肆",
			"伍", "陆", "柒", "捌", "玖" };

	/**
	 * 繁体数字单位
	 */
	public static String[] UNITS_CN = new String[] { "厘", "分", "角", "圆", "拾",
			"佰", "仟", "萬", "億" };

	/**
	 * 最大金额（厘）：9万亿
	 */
	public static final long MAX_MONEY = 999999999999999L;
	/**
	 * 最小金额（厘）：-9万亿
	 */
	public static final long MIN_MONEY = -999999999999999L;

	/**
	 * 把数字/单位转成简体
	 */
	private static void convertSimplified() {
		DIGITS_CN = new String[] { "零", "一", "二", "三", "四", "五", "六", "七", "八",
				"九" };

		UNITS_CN = new String[] { "厘", "分", "角", "元", "十", "百", "千", "万", "亿" };
	}

	/**
	 * 把数字/单位转成繁体
	 */
	private static void convertTraditional() {
		DIGITS_CN = new String[] { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌",
				"玖" };

		UNITS_CN = new String[] { "厘", "分", "角", "圆", "拾", "佰", "仟", "萬", "億" };
	}

	/**
	 * 换为简体汉字，厘以下的四舍五入
	 * 
	 * @param money
	 *            金额（元）
	 * @return
	 */
	public static String toSimplifiedChinese(double money) {
		long lMoney = Math.round(money * 1000);
		return toSimplifiedChinese(lMoney);
	}

	/**
	 * 转换为简体汉字
	 * 
	 * @param money
	 * @return
	 */
	public static String toSimplifiedChinese(long money) {
		convertSimplified();
		return toChinese(money);
	}

	/**
	 * 转换为繁体汉字，厘以下的四舍五入
	 * 
	 * @param money
	 *            金额（元）
	 * @return
	 */
	public static String toTraditionalChinese(double money) {
		long lMoney = Math.round(money * 1000);
		return toTraditionalChinese(lMoney);
	}

	/**
	 * 转换为繁体汉字
	 * 
	 * @param money
	 *            金额（厘）
	 * @return
	 */
	public static String toTraditionalChinese(long money) {
		convertTraditional();
		return toChinese(money);
	}

	/**
	 * 把数字金额转换为汉字
	 * 
	 * @param amount
	 *            金额（厘）
	 * @return
	 */
	private static String toChinese(long money) {
		// 负9千亿 - 9千亿
		if (money > MAX_MONEY || money < MIN_MONEY) {
			throw new IllegalArgumentException(
					"参数值超出允许范围 (-9999 9999 9999.999 ～ 9999 9999 9999.999)元！");
		}

		// 负数标记
		boolean negative = false;
		if (money < 0) {
			negative = true;
			money = money * (-1);
		}

		// 厘
		int moneyLi = (int) (money % 10);
		// 分
		int moneyFen = (int) ((money / 10) % 10);
		// 角
		int moneyJiao = (int) ((money / 100) % 10);
		// 元
		long moneyYuan = money / 1000;

		StringBuffer buffer = new StringBuffer();

		// 把原金额[元]部分按照4位为一组来处理（元/万元/亿元）
		long[] parts = new long[3];
		for (int i = 0; i < 3; i++) {
			long part = moneyYuan % 10000;
			parts[i] = part;
			moneyYuan = moneyYuan / 10000;

			if (moneyYuan == 0) {
				break;
			}
		}

		// 亿
		if (parts[2] != 0) {
			buffer.append(partTranslate(parts[2])).append(UNITS_CN[8]);
		}
		// 万
		if (parts[1] != 0) {
			if (parts[1] < 1000 && buffer.length() != 0) {
				// 如果对应part<1000且高位有值则加[零]
				buffer.append(DIGITS_CN[0]);
			}
			buffer.append(partTranslate(parts[1])).append(UNITS_CN[7]);
		}
		// 元
		if (parts[0] != 0) {
			if (parts[0] < 1000 && buffer.length() != 0) {
				// 如果对应part<1000且高位有值则加[零]
				buffer.append(DIGITS_CN[0]);
			}
			buffer.append(partTranslate(parts[0])).append(UNITS_CN[3]);
		}

		// 角分厘
		if (moneyJiao != 0 || moneyFen != 0 || moneyLi != 0) {
			StringBuffer temp = new StringBuffer();
			if (moneyJiao != 0) {
				temp.append(DIGITS_CN[moneyJiao]).append(UNITS_CN[2]);
			} else {
				temp.append(DIGITS_CN[0]);
			}

			if (moneyFen != 0) {
				temp.append(DIGITS_CN[moneyFen]).append(UNITS_CN[1]);
			} else if (temp.length() == 0) {
				temp.append(DIGITS_CN[0]);
			}

			if (moneyLi != 0) {
				temp.append(DIGITS_CN[moneyLi]).append(UNITS_CN[0]);
			} else if (temp.length() == 0) {
				temp.append(DIGITS_CN[0]);
			}

			buffer.append(temp);
		} else {
			buffer.append("整");
		}

		if (negative) {
			buffer.insert(0, " 负");
		}

		return buffer.toString();
	}

	/**
	 * 把一个 0~9999 之间的整数转换为汉字的字符串，如果是 0 则返回 ""
	 * 
	 * @param moneytPart
	 * @return
	 */
	public static String partTranslate(long moneytPart) {
		if (moneytPart < 0 || moneytPart > 10000) {
			throw new IllegalArgumentException("参数必须是大于等于 0，小于 10000 的整数！");
		}
		// 获取4位数的单位
		String[] units = { "", UNITS_CN[4], UNITS_CN[5], UNITS_CN[6] };

		int moneyLength = new Long(moneytPart).toString().length();
		int temp = (int) moneytPart;
		// 在从低位往高位循环时，记录上一位数字值。
		int lastDigit = 0;
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < moneyLength; i++) {
			if (temp == 0) {
				// 高位已无数据
				break;
			}
			int digit = temp % 10;

			if (digit == 0 && lastDigit != 0) {
				// 当前位为0且上一位不为0则加零
				buffer.insert(0, DIGITS_CN[0]);
			} else if (digit != 0) {
				buffer.insert(0, units[i]);
				buffer.insert(0, DIGITS_CN[digit]);
			}

			lastDigit = digit;
			temp = temp / 10;
		}
		return buffer.toString();
	}

	public static void main(String[] args) {
		System.out.println(toTraditionalChinese(100230045600.789));
		System.out.println(toSimplifiedChinese(100230045600.789));
		System.out.println(toTraditionalChinese(100230045600789L));
		System.out.println(toSimplifiedChinese(100230045600789L));

		for (int i = 0; i < 5; i++) {
			Date d1 = new Date();
			for (int j = 0; j < 10000000; j++) {
				toTraditionalChinese(100230045600.789);
			}
			Date d2 = new Date();
			System.out.println(d2.getTime() - d1.getTime());
		}
	}

}
